﻿using blackhouse.WebNemo.Business.Groups;
using System;
using System.Collections.Generic;
using System.Globalization;
using System.Linq;
using System.Text;
using System.Web;

namespace blackhouse.WebNemo.Web {
    public class NemoUrl : InstanceFactory<NemoUrl> {

        #region Instance

        public static NemoUrl Get() {
            NemoUrl inst = Instance("NemoUrl", typeof(NemoUrl));
            if (inst != null)
                inst.Reset();
            return inst;
        }

        #endregion

        #region Fields

        private string[] preservedQueryKeys = new string[] { "groupid", "recordid", "translate", "mod", "df", "message", "returnurl" };
        private Dictionary<string, string> specialParameters = new Dictionary<string, string>(System.StringComparer.InvariantCultureIgnoreCase);
        private HttpRequest currentRequest = HttpContext.Current.Request;
        private string message;
        public bool addReturnUrl;

        #endregion

        #region Properties

        public NemoUrlView View { get; set; }
        public int GroupId { get; set; }
        public int RecordId { get; set; }
        public CultureInfo Translate { get; set; }
        public string IdentyficatorFormat { get; set; }
        public bool AutoClose { get; set; }
        public bool AddReturnUrl {
            get { return this.addReturnUrl || !this.AutoClose; }
            set { this.addReturnUrl = value; }
        }
        public GroupType GroupType { get; set; }
        public bool HaveReturnUrl {
            get { return !String.IsNullOrEmpty(this.RequestReturnUrl); }
        }
        public string RequestReturnUrl { get; private set; }
        public bool MissingInReturnHistory { get; set; }

        #endregion

        #region Constructors

        public NemoUrl(NemoUrlView view)
            : this() {
            this.View = view;
        }

        public NemoUrl() {
            this.Reset();
        }

        #endregion

        #region Methods

        private void Reset() {
            this.specialParameters.Clear();
            this.currentRequest = HttpContext.Current.Request;
            this.message = String.Empty;

            this.View = this.GetCurrentPage();
            this.GroupId = this.GetCurrentGroupId();
            this.RecordId = this.GetCurrentRecordId();
            this.Translate = this.GetCurrentTranslate();
            this.IdentyficatorFormat = this.GetCurrentIdentyficatorDisplay();
            this.AutoClose = this.currentRequest.QueryString["autoClose"] == "1";
            this.GroupType = this.GetCurrentGroupType();
            this.RequestReturnUrl = HttpUtility.UrlDecode(this.currentRequest.QueryString["returnUrl"]);
            this.MissingInReturnHistory = false;
            foreach (string qKey in this.currentRequest.QueryString.AllKeys)
                this.AddSpecialParameter(qKey, this.currentRequest.QueryString[qKey]);
        }

        public bool AddSpecialParameter(string key, string value) {
            if (this.preservedQueryKeys.Contains(key.ToLower())) return false;
            this.specialParameters[key] = value;
            return true;
        }

        public virtual string GetUrl() {
            StringBuilder urlBuild = new StringBuilder("/Nemo/");
            urlBuild.Append(this.GetDestinationPage());
            if (this.GroupId > 0)
                urlBuild.Append("&groupId=" + this.GroupId);
            if (this.RecordId > 0)
                urlBuild.Append("&recordId=" + this.RecordId);
            if (Enum.IsDefined(typeof(GroupType), this.GroupType))
                urlBuild.Append("&gtype=" + this.GroupType.ToString().ToLower());
            if (this.Translate != null)
                urlBuild.Append("&translate=" + this.Translate.Name);
            if (!String.IsNullOrEmpty(this.IdentyficatorFormat))
                urlBuild.Append("&df=" + HttpUtility.UrlEncode(this.IdentyficatorFormat));
            if (!String.IsNullOrEmpty(this.message))
                urlBuild.Append("&message=" + message);
            foreach (KeyValuePair<string, string> entry in this.specialParameters) {
                urlBuild.AppendFormat("&{0}={1}", entry.Key, entry.Value);
            }
            if (this.AutoClose)
                urlBuild.Append("&autoClose=1");

            if (this.AddReturnUrl) {
                string returnUrl = (this.MissingInReturnHistory) ? this.RequestReturnUrl : HttpUtility.UrlEncode(this.currentRequest.RawUrl);
                returnUrl = returnUrl.ReplaceEx("&message=" + NemoMessage.SaveOk.Key, "").ReplaceEx("&message=" + NemoMessage.RecordRemoved.Key, "");
                urlBuild.Append("&returnUrl=" + returnUrl);
            }

            string url = urlBuild.ToString();
            int idParamChar = url.IndexOf('&');
            url = url.Substring(0, idParamChar) + '?' + url.Substring(idParamChar + 1);
            return url;
        }

        private string GetDestinationPage() {
            switch (this.View) {
                case NemoUrlView.RecordList:
                    return "GroupListing.aspx";
                case NemoUrlView.EditRecord:
                    return "EditRecord.aspx";
                case NemoUrlView.Preview:
                    return "DisplayRecord.aspx";
                case NemoUrlView.Translate:
                    return "EditTranslate.aspx";
                case NemoUrlView.EditGroup:
                    return "Manager/Group.aspx";
                case NemoUrlView.Manager:
                    return "Manager/Default.aspx";
                case NemoUrlView.ManageColumns:
                    return "Manager/GroupColumns.aspx";
                default:
                    return "WebNemoStart.aspx";
            }
        }

        private NemoUrlView GetCurrentPage() {
            string url = this.currentRequest.RawUrl;
            if (url.Contains("Nemo/GroupListing.aspx"))
                return NemoUrlView.RecordList;
            if (url.Contains("Nemo/EditRecord.aspx"))
                return NemoUrlView.EditRecord;
            if (url.Contains("Nemo/DisplayRecord.aspx"))
                return NemoUrlView.Preview;
            if (url.Contains("Nemo/EditTranslate.aspx"))
                return NemoUrlView.Translate;
            return (NemoUrlView)(-1);
        }

        private string GetCurrentIdentyficatorDisplay() {
            return this.currentRequest.QueryString["df"];
        }

        private CultureInfo GetCurrentTranslate() {
            string name = this.currentRequest.QueryString["translate"];
            if (String.IsNullOrEmpty(name)) return null;
            try {
                CultureInfo ci = CultureInfo.GetCultureInfo(name);
                return ci;
            }
            catch {
                return null;
            }
        }

        private int GetCurrentRecordId() {
            return this.GetInt32FromQueryString("recordId");
        }

        private int GetCurrentGroupId() {
            return this.GetInt32FromQueryString("groupId");
        }

        private GroupType GetCurrentGroupType() {
            string sGroupType = this.currentRequest.QueryString["gtype"];
            if (!String.IsNullOrEmpty(sGroupType)) {
                GroupType type = Business.Groups.GroupType.Table;
                if (Enum.TryParse<GroupType>(sGroupType, true, out type))
                    return type;
            }
            return ((GroupType) - 1);
        }

        private int GetInt32FromQueryString(string key) {
            string sVal = this.currentRequest.QueryString[key];
            if (!String.IsNullOrEmpty(sVal)) {
                int val = 0;
                if (Int32.TryParse(sVal, out val))
                    return val;
            }
            return 0;
        }

        public void ShowMessage(NemoMessage message) {
            this.message = message.Key;
        }

        #endregion

    }

    public enum NemoUrlView {
        RecordList,
        EditRecord,
        Preview,
        Translate,
        EditGroup,
        Manager,
        ManageColumns
    }

}